home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 22 / Cream of the Crop 22.iso / disk / cluster2.zip / SOURCE.ZIP / PB3BOXES.BU < prev    next >
Text File  |  1996-06-16  |  30KB  |  811 lines

  1. '╒═══════════════════════════════════════════════════════════════════════════╕
  2. '│                                                                           │
  3. '│  Text Screen routines for PowerBASIC                                      │
  4. '│  Copyright (c) 1995 by PowerBASIC, Inc.  All Rights Reserved.             │
  5. '│                                                                           │
  6. '│  Note:  These routines are written for maximum speed and will have to be  │
  7. '│         modified to prevent snow on older CGA cards.                      │
  8. '│                                                                           │
  9. '├───────────────────────────────────────────────────────────────────────────┤
  10. '│                                                                           │
  11. '│  LineEdit    -  Edit a line of text; can be longer than the edit window   │
  12. '│  LineInput   -  Get a line of text from the user with a specified limit   │
  13. '│  PgCopy      -  Copy one Text video page to another on a color screen     │
  14. '│  QATTR       -  Change the background attributes of a given location      │
  15. '│  QBOX        -  Display a text box with in a specified color              │
  16. '│  QFILL       -  Fill a specified location with a char and attribute       │
  17. '│  QPRINT      -  Quickly print a string to the screen                      │
  18. '│  QPRINTC     -  Quickly print a centered string to the screen             │
  19. '│  QREST       -  Restore a saved portion of the screen                     │
  20. '│  QSAVE       -  Save a portion of the screen                              │
  21. '│  ScrollDown  -  Scroll a specified portion of the screen down             │
  22. '│  ScrollUp    -  Scroll a specified portion of the screen up               │
  23. '│  SetBlink    -  Change the blink bit status on EGA/VGA text screens       │
  24. '│                                                                           │
  25. '├───────────────────────────────────────────────────────────────────────────┤
  26. '│                                                                           │
  27. '│ 10 June 96 --  Bud Durland                                                │
  28. '│                                                                           │
  29. '│  Modified to store saved screen areas in dynamic strings;  minor bug      │
  30. '│  in QATTR corrected; input routine changed for more control.              │
  31. '│                                                                           │
  32. '│   The original routines in SCRNUNIT were written to save screen           │
  33. '│   areas inINTEGER arrays.  This is OK if you are only doing one box at    │
  34. '│   a time, but is expensive in terms of memory for multiple boxes.         │
  35. '│   Using strings to save screen areas is more economical, since you can    │
  36. '│   create a string array for however many boxes you will be using, and     │
  37. '│   dynamic strings will then only consume enough memory to hold the        │
  38. '│   screen area specified.  An integer array would always have to be        │
  39. '│   dimensioned for the largest possible screen area.                       │
  40. '│                                                                           │
  41. '╘═══════════════════════════════════════════════════════════════════════════╛
  42.  
  43.  
  44. $COMPILE UNIT ".\SCRNUNIT.PBU"
  45. $CODE SEG "SCRNLIB"
  46. $CPU      8086      ' Make compatible with XT systems
  47. $LIB      ALL OFF   ' Turn off all PowerBASIC libraries
  48. $ERROR    ALL OFF   ' Turn off all PowerBASIC error checking
  49. $OPTIMIZE SIZE      ' Optimize for smaller code
  50.  
  51. DEFINT    A-Z       ' Required for all numeric functions, forces PB to not
  52.                     ' include floating point in UNIT (makes it smaller)
  53.  
  54. DECLARE SUB GetStrLoc()     ' internal string locator in RTL
  55.  
  56.  
  57. $INCLUDE ".\PB3BOXES.HDR"      ' includes defs & declares for all modules.
  58.  
  59.  
  60. '===========================================================================
  61. ' QSAVE - saves specified portion of a text screen in a string
  62. '
  63. ' Row   = Starting screen row of area to save
  64. ' Col   = Starting screen column of area to save
  65. ' Rows  = Number of rows to save (must be 1 or greater)
  66. ' Cols  = Number of columns to save (must be 1 or greater)
  67. ' Where = string where data is to be saved
  68. '
  69. SUB QSAVE(BYVAL Row  AS INTEGER, BYVAL Col  AS INTEGER, _
  70.           BYVAL Rows AS INTEGER, BYVAL Cols AS INTEGER, _
  71.           Where AS STRING) LOCAL PUBLIC
  72.  
  73.   DIM ScrnSeg AS INTEGER
  74.   DIM WhereMem AS DWORD
  75.  
  76.   IF (pbvScrnCard AND 1) = 0 THEN
  77.     ScrnSeg = &HB800        ' color monitor
  78.   ELSE
  79.     ScrnSeg = &HB000        ' mono monitor
  80.   END IF
  81.  
  82.   dLen% = (Rows * Cols) * 2                     ' how much data to store?
  83.   Where = LEFT$(Where + SPACE$(dLen%),dLen%)    ' make string long enough
  84.   WhereMem = STRPTR32(Where)
  85.  
  86.   ! push DS                 ; save DS for PowerBASIC
  87.  
  88.   ! les  DI, WhereMem       ; put location of array element in ES:DI
  89.   ! mov  AX, ScrnSeg        ; put screen segment in AX
  90.   ! mov  DS, AX             ; move to DS
  91.  
  92.   ! mov  AX, Row            ; put row in AX
  93.   ! dec  AX                 ; minus one
  94.   ! mov  CX, 160            ; AX =
  95.   ! mul  CX                 ;   AX * 160
  96.   ! mov  SI, AX             ; put it in SI
  97.   ! mov  AX, Col            ; put column in AX
  98.   ! dec  AX                 ; minus one
  99.   ! shl  AX, 1              ; times 2
  100.   ! add  SI, AX             ; add to SI
  101.   ! mov  DX, Rows           ; put rows in DX
  102. SaveRow:
  103.   ! mov  CX, Cols           ; put number of columns in CX
  104.   ! push SI                 ; save screen offset
  105.   ! rep  movsw              ; copy CX words to array from screen
  106.   ! pop  SI                 ; restore screen offset
  107.   ! add  SI, 160            ; move to next row
  108.   ! dec  DX                 ; one less row to do
  109.   ! jnz  SaveRow            ; if it's zero, we're done
  110.  
  111.   ! pop  DS                 ; restore DS for PowerBASIC
  112.  
  113. END SUB
  114.  
  115.  
  116. '===========================================================================
  117. ' QREST - Restores specified portion of a text screen from a string
  118. '
  119. ' Row   = Starting screen row of area to restore
  120. ' Col   = Starting screen column of area to restore
  121. ' Rows  = Number of rows to restore (must be 1 or greater)
  122. ' Cols  = Number of columns to restore (must be 1 or greater)
  123. ' Where = Starting element of integer array where data is to be restored from
  124. '
  125. SUB QREST(BYVAL Row  AS INTEGER, BYVAL Col  AS INTEGER, _
  126.           BYVAL Rows AS INTEGER, BYVAL Cols AS INTEGER, _
  127.           Where AS STRING) LOCAL PUBLIC
  128.  
  129.   DIM ScrnSeg AS INTEGER
  130.   DIM WhereMem AS DWORD
  131.  
  132.   IF (pbvScrnCard AND 1) = 0 THEN
  133.     ScrnSeg = &HB800        ' color monitor
  134.   ELSE
  135.     ScrnSeg = &HB000        ' mono monitor
  136.   END IF
  137.  
  138.   WhereMem = STRPTR32(Where)  ' point to data in string
  139.  
  140.   ! push DS                 ; save DS for PowerBASIC
  141.  
  142.   ! lds  SI, WhereMem       ; put location of array in DS:SI
  143.   ! mov  AX, ScrnSeg        ; put screen segment in AX
  144.   ! mov  ES, AX             ; move to ES
  145.  
  146.   ! mov  AX, Row            ; put row in AX
  147.   ! dec  AX                 ; minus one
  148.   ! mov  CX, 160            ; AX =
  149.   ! mul  CX                 ;   AX * 160
  150.   ! mov  DI, AX             ; put it in DI
  151.   ! mov  AX, Col            ; put column in AX
  152.   ! dec  AX                 ; minus one
  153.   ! shl  AX, 1              ; times 2
  154.   ! add  DI, AX             ; add to DI
  155.   ! mov  DX, Rows           ; put rows in DX
  156. RestoreRow:
  157.   ! mov  CX, Cols           ; put number of columns in CX
  158.   ! push DI                 ; save screen offset
  159.   ! rep  movsw              ; copy CX words to array from screen
  160.   ! pop  DI                 ; restore screen offset
  161.   ! add  DI, 160            ; move to next row
  162.   ! dec  DX                 ; one less row to do
  163.   ! jnz  RestoreRow         ; if it's zero, we're done
  164.  
  165.   ! pop  DS                 ; restore DS for PowerBASIC
  166.  
  167. END SUB
  168.  
  169.  
  170. '===========================================================================
  171. ' QBOX - Display a box on the screen
  172. '
  173. ' Row  = Starting screen row of box
  174. ' Col  = Starting screen column of box
  175. ' Rows = Number of rows for the box
  176. ' Cols = Number of columns for the box
  177. ' Attr = Color attribute of the box
  178. '
  179. SUB QBOX(BYVAL Row  AS INTEGER, BYVAL Col  AS INTEGER, _
  180.          BYVAL Rows AS INTEGER, BYVAL Cols AS INTEGER, _
  181.          BYVAL Attr AS INTEGER, BYVAL Bord AS INTEGER) PUBLIC
  182.  
  183.   DIM ScrnSeg AS INTEGER
  184.   DIM TL.Char AS BYTE
  185.   DIM Vert    AS BYTE
  186.   DIM TR.Char AS BYTE
  187.   DIM Horiz   AS BYTE
  188.   DIM BL.Char AS BYTE
  189.   DIM BR.Char AS BYTE
  190.  
  191.   IF (pbvScrnCard AND 1) = 0 THEN
  192.     ScrnSeg = &HB800        ' color monitor
  193.   ELSE
  194.     ScrnSeg = &HB000        ' mono monitor
  195.   END IF
  196.  
  197.   Horiz?   = ASC(MID$(BorderText$(Bord),1,1))
  198.   Vert?    = ASC(MID$(BorderText$(Bord),2,1))
  199.   TL.Char? = ASC(MID$(BorderText$(Bord),3,1))
  200.   TR.Char? = ASC(MID$(BorderText$(Bord),4,1))
  201.   BL.Char? = ASC(MID$(BorderText$(Bord),5,1))
  202.   BR.Char? = ASC(MID$(BorderText$(Bord),6,1))
  203.  
  204.   ! push DS                 ; save DS for PowerBASIC
  205.  
  206.   ! mov  AX, ScrnSeg        ; put screen segment in AX
  207.   ! mov  ES, AX             ;  and in ES
  208.  
  209.   ! mov  AX, Row            ; put row in AX
  210.   ! dec  AX                 ; minus one
  211.   ! mov  CX, 160            ; AX =
  212.   ! mul  CX                 ;   AX * 160
  213.   ! mov  DI, AX             ; put it in DI
  214.   ! mov  AX, Col            ; put column in AX
  215.   ! dec  AX                 ; minus one
  216.   ! shl  AX, 1              ; times 2
  217.   ! add  DI, AX             ; add to DI
  218.  
  219.   ! mov  DX, Rows           ; put rows in DX
  220.   ! dec  DX                 ; minus top row
  221.   ! dec  DX                 ; minus bottom row
  222.  
  223.   ! mov  CX, Cols           ; put columns in CX
  224.   ! dec  CX                 ; minus left column
  225.   ! dec  CX                 ; minus right column
  226.  
  227.   ! mov  AH, Attr           ; put attribute in AH
  228.  
  229.   ! push CX                 ; save CX (columns)
  230.   ! push DI                 ;  and DI (screen location)
  231.   ! mov  AL, TL.Char?       ; put top left char in AL
  232.   ! stosw                   ; write it to the screen
  233.   ! mov  AL, Horiz?         ; put top char in AL
  234.   ! rep  stosw              ; write it to the screen CX times
  235.   ! mov  AL, TR.Char?       ; put top right char in AL
  236.   ! stosw                   ; write it to the screen
  237.   ! pop  DI                 ; restore DI
  238.   ! pop  CX                 ;  and CX
  239. HorizLoop:
  240.   ! add  DI, 160            ; move to next row on the screen
  241.   ! push CX                 ; save CX
  242.   ! push DI                 ;  and DI
  243.   ! mov  AL, Vert?          ; put left char in AL
  244.   ! stosw                   ; write it to the screen
  245.   ! mov  AL, 32             ; put a space in AL
  246.   ! rep  stosw              ; write it to the screen CX times
  247.   ! mov  AL, Vert?          ; put right char in AL
  248.   ! stosw                   ; write it to the screen
  249.   ! pop  DI                 ; restore DI
  250.   ! pop  CX                 ;  and CX
  251.   ! dec  DX                 ; one less row
  252.   ! jnz  HorizLoop          ; loop until DX (rows) = 0
  253.  
  254.   ! add  DI, 160            ; move to next row on the screen
  255.   ! mov  AL, BL.Char?       ; put bottom left char in AL
  256.   ! stosw                   ; write it to the screen
  257.   ! mov  AL, Horiz?         ; put bottom char in AL
  258.   ! rep  stosw              ; write it to the screen CX times
  259.   ! mov  AL, BR.Char?       ; put bottom right char in AL
  260.   ! stosw                   ; write it to the screen
  261.  
  262.   ! pop  DS                 ; restore DS for PowerBASIC
  263.  
  264. END SUB
  265.  
  266.  
  267. '===========================================================================
  268. ' QFILL - fill area of the screen with specified character and attribute
  269. '
  270. ' Row   = Starting screen row of area to fill
  271. ' Col   = Starting screen column of area to fill
  272. ' Rows  = Number of rows to fill (must be 1 or greater)
  273. ' Cols  = Number of columns to fill (must be 1 or greater)
  274. ' Char  = ASCII character to fill block with
  275. ' Attr  = Color attribute to fill block with
  276. '
  277. SUB QFILL(BYVAL Row  AS INTEGER, BYVAL Col  AS INTEGER, _
  278.           BYVAL Rows AS INTEGER, BYVAL Cols AS INTEGER, _
  279.           BYVAL Char AS INTEGER, BYVAL Attr AS INTEGER) PUBLIC
  280.  
  281.   DIM ScrnSeg AS INTEGER
  282.  
  283.   IF (pbvScrnCard AND 1) = 0 THEN
  284.     ScrnSeg = &HB800        ' color monitor
  285.   ELSE
  286.     ScrnSeg = &HB000        ' mono monitor
  287.   END IF
  288.  
  289.   ! push DS                 ; save DS for PowerBASIC
  290.  
  291.   ! mov  AX, ScrnSeg        ; put screen segment in AX
  292.   ! mov  ES, AX             ;  and in ES
  293.  
  294.   ! mov  AX, Row            ; put row in AX
  295.   ! dec  AX                 ; minus one
  296.   ! mov  CX, 160            ; AX =
  297.   ! mul  CX                 ;   AX * 160
  298.   ! mov  DI, AX             ; put it in DI
  299.   ! mov  AX, Col            ; put column in AX
  300.   ! dec  AX                 ; minus one
  301.   ! shl  AX, 1              ; times 2
  302.   ! add  DI, AX             ; add to DI
  303.   ! mov  DX, Rows           ; put rows in DX
  304.  
  305.   ! mov  AX, Char           ; put character in AX
  306.   ! mov  AH, Byte Ptr Attr  ; put attribute in AH
  307.   ! mov  CX, Cols           ; put columns in CX
  308. FillRow:
  309.   ! push DI                 ; save DI
  310.   ! push CX                 ; save CX
  311.   ! rep  stosw              ; write CX words
  312.   ! pop  CX                 ; restore CX
  313.   ! pop  DI                 ; restore DI
  314.   ! add  DI, 160            ; move to next row
  315.   ! dec  DX                 ; one less row
  316.   ! jnz  FillRow            ; loop until DX = 0
  317.  
  318.   ! pop  DS                 ; restore DS for PowerBASIC
  319.  
  320. END SUB
  321.  
  322.  
  323. '===========================================================================
  324. ' QATTR - fill area of the screen with specified attribute
  325. '
  326. ' Row   = Starting screen row of area to fill
  327. ' Col   = Starting screen column of area to fill
  328. ' Rows  = Number of rows to fill (must be 1 or greater)
  329. ' Cols  = Number of columns to fill (must be 1 or greater)
  330. ' Attr  = Color attribute to fill block with
  331. '
  332. SUB QATTR(BYVAL Row  AS INTEGER, BYVAL Col  AS INTEGER, _
  333.           BYVAL Rows AS INTEGER, BYVAL Cols AS INTEGER, _
  334.           BYVAL Attr AS INTEGER) PUBLIC
  335.  
  336.   DIM ScrnSeg AS INTEGER
  337.  
  338.   IF (pbvScrnCard AND 1) = 0 THEN
  339.     ScrnSeg = &HB800        ' color monitor
  340.   ELSE
  341.     ScrnSeg = &HB000        ' mono monitor
  342.   END IF
  343.  
  344.   ! push DS                 ; save DS for PowerBASIC
  345.  
  346.   ! mov  AX, ScrnSeg        ; put screen segment in AX
  347.   ! mov  ES, AX             ;  and in ES
  348.  
  349.   ! mov  AX, Row            ; put row in AX
  350.   ! dec  AX                 ; minus one
  351.   ! mov  CX, 160            ; AX =
  352.   ! mul  CX                 ;   AX * 160
  353.   ! mov  DI, AX             ; put it in DI
  354.   ! mov  AX, Col            ; put column in AX
  355.   ! dec  AX                 ; minus one
  356.   ! shl  AX, 1              ; times 2
  357.   ! add  DI, AX             ; add to DI
  358.   ! mov  DX, Rows           ; put rows in DX
  359.  
  360.   ! mov  AL, Byte Ptr Attr  ; put attribute in AL
  361.   ! mov  CX, Cols           ; put columns in CX
  362. RecolorRow:
  363.   ! push DI                 ; save DI
  364.   ! push CX                 ; save CX
  365.  
  366. RecolorCol:
  367.   ! inc  DI                 ; skip character    ' was after stosb -- bug
  368.   ! stosb                   ; write attribute
  369.   ! loop RecolorCol         ; do it CX times
  370.  
  371.   ! pop  CX                 ; restore CX
  372.   ! pop  DI                 ; restore DI
  373.   ! add  DI, 160            ; move to next row
  374.   ! dec  DX                 ; one less row
  375.   ! jnz  RecolorRow         ; loop until DX = 0
  376.  
  377.   ! pop  DS                 ; restore DS for PowerBASIC
  378.  
  379. END SUB
  380.  
  381.  
  382. '===========================================================================
  383. ' QPRINT - print string to specified location on the screen in specified color
  384. '
  385. ' Note:  String is passed BYVAL to make it compatible with fixed length
  386. '        and flex strings.  Since this uses the internal assembler, PB will
  387. '        automatically release the temporary string handle left on the stack.
  388. '        If it were an external assembler routine, it would be responsible for
  389. '        releasing the string.
  390. '
  391. ' Row   = Screen row to display text
  392. ' Col   = Starting column to display text
  393. ' Text  = Text string to display on screen
  394. ' Attr  = Color attribute to display characters
  395. '
  396. SUB QPRINT(BYVAL Row  AS INTEGER, BYVAL Col AS INTEGER, _
  397.            BYVAL Text AS STRING, BYVAL Attr AS INTEGER) PUBLIC
  398.  
  399.   DIM ScrnSeg AS INTEGER
  400.  
  401.   IF (pbvScrnCard AND 1) = 0 THEN
  402.     ScrnSeg = &HB800        ' color monitor
  403.   ELSE
  404.     ScrnSeg = &HB000        ' mono monitor
  405.   END IF
  406.  
  407.   ! push DS                 ; save DS for PowerBASIC
  408.  
  409.   ! push Word Ptr Text      ; push string handle on the stack
  410.   ! call GetStrLoc          ; find the string
  411.   ! jcxz QPExit             ; if it's null, exit
  412.  
  413.   ! mov  DS, DX             ; put segment in DS
  414.   ! mov  SI, AX             ; put offset in SI
  415.   ! push CX                 ; save length
  416.  
  417.   ! mov  AX, ScrnSeg        ; put screen segment in AX
  418.   ! mov  ES, AX             ; move to ES
  419.  
  420.   ! mov  AX, Row            ; put row in AX
  421.   ! dec  AX                 ; minus one
  422.   ! mov  CX, 160            ; AX =
  423.   ! mul  CX                 ;   AX * 160
  424.   ! mov  DI, AX             ; put it in DI
  425.   ! mov  AX, Col            ; put column in AX
  426.   ! dec  AX                 ; minus one
  427.   ! shl  AX, 1              ; times 2
  428.   ! add  DI, AX             ; add to DI
  429.  
  430.   ! pop  CX                 ; restore length of string
  431.   ! mov  AH, Attr           ; put attribute in AH
  432. WriteChar:
  433.   ! lodsb                   ; get char from string
  434.   ! stosw                   ; write char and attribute to screen
  435.   ! loop WriteChar          ; do it all CX times
  436. QPExit:
  437.   ! pop  DS                 ; restore DS for PowerBASIC
  438.  
  439. END SUB
  440.  
  441.  
  442. '===========================================================================
  443. ' QPRINTC - Print a string centered between two columns on the specified
  444. '           row.
  445. '
  446. ' Row   = Screen row to display text
  447. ' ColL  = Starting column to center displayed text
  448. ' ColR  = Ending column to center displayed text
  449. ' Text$ = Text string to display on screen
  450. ' Attr  = Color attribute to display characters
  451. '
  452. SUB QPRINTC(BYVAL Row  AS INTEGER, BYVAL ColL AS INTEGER, _
  453.             BYVAL ColR AS INTEGER, BYVAL Text AS STRING, _
  454.             BYVAL Attr AS INTEGER)
  455.  
  456.   DIM Temp AS INTEGER
  457.  
  458.   Temp = (ColL + ((ColR - ColL) \ 2)) - (LEN(Text$) \ 2)
  459.  
  460.   QPRINT Row, Temp, Text$, Attr
  461.  
  462. END SUB
  463.  
  464.  
  465. '===========================================================================
  466. ' SetBlink - Change the status of the blink bit on EGA/VGA color monitors.
  467. '
  468. ' Status - A zero indicates a normal blink bit.  A non-zero indicates
  469. '          the blink bit is a high-intensity background.
  470. '
  471. SUB SetBlink(BYVAL Status AS INTEGER)
  472.  
  473.   IF BIT(pbvScrnCard, 4) THEN       ' only works on EGA/VGA monitors
  474.     Status = (Status <> 0) AND 1    ' convert to 0 or 1
  475.     ! mov AX, &H1003
  476.     ! mov BX, Status
  477.     ! int &H10
  478.   END IF
  479.  
  480. END SUB
  481.  
  482.  
  483. '===========================================================================
  484. ' PgCopy - Copy data from one text page to another
  485. '
  486. ' SourcePage = Text page to copy from (starts with 0)
  487. ' TargetPage = Text page to copy to (starts with 0)
  488. '
  489. SUB PgCopy(BYVAL SourcePage AS INTEGER, BYVAL TargetPage AS INTEGER) PUBLIC
  490.  
  491.   DIM PageSize AS INTEGER
  492.   DIM ScrnSeg  AS INTEGER
  493.  
  494.   IF (pbvScrnCard AND 1) = 1 THEN  ' monochrome adaptor only has 1 page
  495.     EXIT SUB
  496.   END IF
  497.  
  498.   IF (pbvScrnRows = 25) AND (pbvScrnCols = 80) THEN
  499.     PageSize = 4096                    ' 80x25 = 4k page; could be buggy CGA
  500.   ELSEIF (pbvScrnRows = 25) AND (pbvScrnCols = 40) THEN
  501.     PageSize = 2048                    ' 40x25 = 2k page; could be buggy CGA
  502.   ELSE
  503.     ! push DS                          ; save DS for PowerBASIC
  504.     ! xor  AX, AX                      ; clear AX
  505.     ! mov  DS, AX                      ;  and DS
  506.     ! mov  AX, DS:[&H044C]             ; get page size from BIOS
  507.     ! mov  PageSize, AX                ; put it in PageSize
  508.     ! pop  DS                          ; restore DS for PowerBASIC
  509.   END IF
  510.  
  511.   SourcePage = SourcePage * PageSize   ' calculate offset of source page
  512.   TargetPage = TargetPage * PageSize   ' calculate offset of target page
  513.   ScrnSeg    = &HB800                  ' only color adaptors have multiple pages
  514.  
  515.   ! push DS                 ; save DS for PowerBASIC
  516.  
  517.   ! mov  AX, ScrnSeg        ; put screen segment in AX
  518.   ! mov  ES, AX             ; and in ES
  519.   ! mov  DS, AX             ; and in DS
  520.  
  521.   ! mov  SI, SourcePage     ; put source page offset in SI
  522.   ! mov  DI, TargetPage     ; put target page offset in DI
  523.  
  524.   ! mov  CX, PageSize       ; put page size in CX
  525.   ! shr  CX, 1              ; divide by two
  526.  
  527.   ! rep  movsw              ; move data as words (faster than bytes)
  528.  
  529.   ! pop  DS                 ; restore DS for PowerBASIC
  530.  
  531. END SUB
  532.  
  533.  
  534. '===========================================================================
  535. ' ScrollUp - Scroll the specified part of the screen up
  536. '
  537. ' Row     = Starting row on screen of scroll area
  538. ' Col     = Starting column on screen of scroll area
  539. ' Rows    = Total rows on screen of scroll area
  540. ' Cols    = Total cols on screen of scroll area
  541. ' Attr    = Color attribute for new blank lines
  542. ' HowMany = How many lines to scroll in specified area
  543. '
  544. SUB ScrollUp(BYVAL Row AS INTEGER, BYVAL Col AS INTEGER, _
  545.              BYVAL Rows AS INTEGER, BYVAL Cols AS INTEGER, _
  546.              BYVAL Attr AS INTEGER, BYVAL HowMany AS INTEGER)
  547.  
  548.   DECR Row                  ' convert Row to 0 base
  549.   DECR Col                  ' convert Col to 0 base
  550.   INCR Rows, Row - 1        ' convert Rows to bottom row coordinate
  551.   INCR Cols, Col - 1        ' convert Cols to right col coordinate
  552.  
  553.   ! push DS                 ; save DS for PowerBASIC
  554.  
  555.   ! mov  AH, 6              ; AH = service 6, scroll up
  556.   ! mov  AL, HowMany        ; AL = number of lines to scroll
  557.   ! mov  BH, Byte Ptr Attr  ; BH = color of new text line
  558.   ! mov  BL, DS:pbvScrnAPage ; BL = active display page
  559.   ! mov  CH, Row            ; CH = starting row
  560.   ! mov  CL, Col            ; CL = starting column
  561.   ! mov  DH, Rows           ; DH = ending row
  562.   ! mov  DL, Cols           ; DL = ending column
  563.   ! int  &H10               ; call Video BIOS
  564.  
  565.   ! pop  DS                 ; restore DS for PowerBASIC
  566.  
  567. END SUB
  568.  
  569.  
  570. '===========================================================================
  571. ' ScrollDown - Scroll the specified part of the screen down
  572. '
  573. ' Row     = Starting row on screen of scroll area
  574. ' Col     = Starting column on screen of scroll area
  575. ' Rows    = Total rows on screen of scroll area
  576. ' Cols    = Total cols on screen of scroll area
  577. ' Attr    = Color attribute for new blank lines
  578. ' HowMany = How many lines to scroll in specified area
  579. '
  580. SUB ScrollDown(BYVAL Row AS INTEGER, BYVAL Col AS INTEGER, _
  581.                BYVAL Rows AS INTEGER, BYVAL Cols AS INTEGER, _
  582.                BYVAL Attr AS INTEGER, BYVAL HowMany AS INTEGER)
  583.  
  584.   DECR Row                  ' convert Row to 0 base
  585.   DECR Col                  ' convert Col to 0 base
  586.   INCR Rows, Row - 1        ' convert Rows to bottom row coordinate
  587.   INCR Cols, Col - 1        ' convert Cols to right col coordinate
  588.  
  589.   ! push DS                 ; save DS for PowerBASIC
  590.  
  591.   ! mov  AH, 7              ; AH = service 6, scroll down
  592.   ! mov  AL, HowMany        ; AL = number of lines to scroll
  593.   ! mov  BH, Byte Ptr Attr  ; BH = color of new text line
  594.   ! mov  BL, DS:pbvScrnAPage ; BL = active display page
  595.   ! mov  CH, Row            ; CH = starting row
  596.   ! mov  CL, Col            ; CL = starting column
  597.   ! mov  DH, Rows           ; DH = ending row
  598.   ! mov  DL, Cols           ; DL = ending column
  599.   ! int  &H10               ; call Video BIOS
  600.  
  601.   ! pop  DS                 ; restore DS for PowerBASIC
  602.  
  603. END SUB
  604.  
  605.  
  606. '===========================================================================
  607. ' LineEdit - Allow the end user to edit a text line
  608. '
  609. ' Row    = Row to display edit field
  610. ' Col    = Column to display edit field
  611. ' Text$  = Text string to edit
  612. ' Attr   = Color attribute to display string
  613. ' EdLen  = Length of edit window
  614. ' MaxLen = Maximum edit length
  615. ''
  616. ' Mods for Library routine -- bud
  617. ' GoodKeys$  =  Keys that can be accepted for input.  Good if you want
  618. '               numerics only, etc.  Case insensitive.
  619. ' TermKeys$  =  What keys will exit this routine;  If this is blank,
  620. '               Enter and Esc are used.
  621. ' ExitKey%   =  tells what key exited this routine.  For two-byte exit keys,
  622. '               (pgUp, DownArrow, etc), this is set to 255 + the ASC of the
  623. '               second byte.
  624. '
  625. SUB LineEdit(BYVAL Row AS INTEGER, BYVAL Col AS INTEGER, _
  626.              Text AS STRING, BYVAL Attr AS INTEGER, _
  627.              BYVAL GoodKeys AS STRING, BYVAL TermKeys AS STRING, _
  628.              ExitKey AS INTEGER, BYVAL EdLen AS INTEGER, _
  629.              BYVAL MaxLen AS INTEGER) PUBLIC
  630.  
  631.   DIM Ins       AS INTEGER
  632.   DIM Cursor    AS INTEGER
  633.   DIM OldCurX   AS INTEGER
  634.   DIM OldCurY   AS INTEGER
  635.   DIM OldCurTop AS INTEGER
  636.   DIM Begin     AS INTEGER
  637.   DIM I         AS STRING
  638.   DIM Temp      AS STRING
  639.  
  640.   IF EdLen > MaxLen THEN
  641.     MaxLen = EdLen
  642.   END IF
  643.  
  644.   Ins       = 0
  645.   Cursor    = 1
  646.   Begin     = 1
  647.   OldCurX   = POS
  648.   OldCurY   = CSRLIN
  649.   OldCurTop = pbvCursor1
  650.   Temp$     = Text$ + SPACE$( MaxLen-LEN(Text$) )
  651.  
  652.   LOCATE Row, Col+Cursor-1, 1
  653.  
  654.   DO
  655.     QPRINT Row, Col, MID$(Temp$, Begin, EdLen), Attr
  656.     LOCATE Row, Col + Cursor - 1
  657.  
  658.     DO
  659.       I$ = INKEY$
  660.     LOOP WHILE LEN(I$) = 0
  661.  
  662.     SELECT CASE I$
  663.       CASE CHR$(27)                      'Esc
  664.         EXIT DO
  665.  
  666.       CASE CHR$(13)                      'Return
  667.         EXIT DO
  668.  
  669.       CASE CHR$(0, 82)                   'Insert
  670.         IF Ins = 0 THEN
  671.           Ins = -1
  672.           LOCATE , , 1, pbvCursor1 - 2, pbvCursor2
  673.         ELSE
  674.           Ins = 0
  675.           LOCATE , , 1, pbvCursor1 + 2, pbvCursor2
  676.         END IF
  677.  
  678.       CASE CHR$(0, 75)                   'Left arrow
  679.         IF (Begin + Cursor - 1) > 1 THEN
  680.           DECR Cursor
  681.           IF Cursor = 0 THEN
  682.             Cursor = 1
  683.             DECR Begin
  684.           END IF
  685.         END IF
  686.  
  687.       CASE CHR$(0, 77)                   'Right arrow
  688.         IF (Begin + Cursor - 1) <= LEN(Temp$) THEN
  689.           INCR Cursor
  690.           IF Cursor > EdLen THEN
  691.             Cursor = EdLen
  692.             INCR Begin
  693.           END IF
  694.         END IF
  695.  
  696.       CASE CHR$(8)                       'Backspace
  697.         IF (Begin + Cursor - 1) > LEN(Temp$) THEN
  698.           Temp$ = LEFT$(Temp$, LEN(Temp$) - 1) + " "
  699.           DECR Cursor
  700.         ELSEIF (Begin + Cursor - 1) > 1 THEN
  701.           Temp$ = LEFT$(Temp$, Begin + Cursor - 3) _
  702.                 + MID$(Temp$, Begin + Cursor - 1) + " "
  703.           DECR Cursor
  704.         END IF
  705.         IF Cursor = 0 THEN
  706.           Cursor = 1
  707.           DECR Begin
  708.         END IF
  709.  
  710.       CASE CHR$(0, 79)                   'End
  711.         Cursor = LEN(RTRIM$(Temp$))+1
  712.         IF Cursor > EdLen THEN
  713.           Begin = Cursor - EdLen + 1
  714.           Cursor = EdLen
  715.         END IF
  716.  
  717.       CASE CHR$(0, 71)                   'Home
  718.         Cursor = 1
  719.         Begin  = 1
  720.  
  721.       CASE ELSE
  722.         IF INSTR(TermKeys, I$) > 0 THEN             ' a termination key
  723.           EXIT DO
  724.         END IF
  725.  
  726.         IF (LEN(GoodKeys) > 0) AND (INSTR(GoodKeys,UCASE$(I$)) = 0) THEN
  727.           ITERATE DO                               ' this key not allowed
  728.         END IF
  729.  
  730.         IF (Begin + Cursor - 1) <= LEN(Temp$) THEN
  731.           IF ASCII(I$) > 31 THEN
  732.             IF Ins = 0 THEN
  733.               MID$(Temp$, Begin + Cursor - 1, 1) = I$
  734.               INCR Cursor
  735.             ELSE
  736.               IF RIGHT$(Temp$, 1) = " " THEN
  737.                 Temp$ = LEFT$(Temp$, Begin+Cursor-2) _
  738.                       + I$ _
  739.                       + MID$(Temp$, Begin+Cursor-1, LEN(Temp$)-(Begin+Cursor-1))
  740.                 INCR Cursor
  741.               END IF
  742.             END IF
  743.           END IF
  744.           IF Cursor > EdLen THEN
  745.             Cursor = EdLen
  746.             INCR Begin
  747.           END IF
  748.         END IF
  749.  
  750.     END SELECT
  751.  
  752.   LOOP
  753.  
  754.   ExitKey% = ASC(I$)
  755.   IF LEN(I$) = 2 THEN ExitKey% = 255 + ASC(MID$(I$,2))
  756.   LOCATE OldCurY, OldCurX, 0, OldCurTop, pbvCursor2
  757.   Text = RTRIM$(Temp)
  758.  
  759. END SUB
  760.  
  761.  
  762. '===========================================================================
  763. ' LineInput - Allow the end user to input a text line with a specified
  764. '             maximum length.  Uses the FLEXCHR$ value to show the maximum
  765. '             field length.
  766. '
  767. ' Default$  = Default for input data
  768. ' MaxLength = Maximum length of input data
  769. '
  770. SUB LineInput(Default AS STRING, BYVAL MaxLength AS INTEGER) PUBLIC
  771.  
  772.   DIM Row       AS INTEGER
  773.   DIM Col       AS INTEGER
  774.   DIM CharCount AS INTEGER
  775.   DIM C         AS STRING
  776.  
  777.   Row       = CSRLIN                'use the current cursor position
  778.   Col       = POS                   '  to mimic LINE INPUT.
  779.   CharCount = LEN(Default$)
  780.  
  781.   DO
  782.     LOCATE Row, Col, 0
  783.     PRINT STRING$(MaxLength, FLEXCHR$);  ' show the size of the field
  784.     LOCATE Row, Col, 1                   ' be sure to turn the cursor on
  785.     PRINT Default$;
  786.     DO
  787.       C$ = INKEY$
  788.     LOOP UNTIL LEN(C$)
  789.     SELECT CASE C$
  790.       CASE CHR$(8)                  'backspace
  791.         IF CharCount > 0 THEN       'If more than zero characters, delete one
  792.           DECR CharCount
  793.           Default$ = LEFT$( Default$, LEN( Default$ ) - 1 )
  794.           LOCATE Row, Col, 0        'turn the cursor off
  795.           PRINT Default$;FLEXCHR$;  'erase the deleted char from the screen
  796.         END IF
  797.       CASE CHR$(13)                 'Return was pressed so end loop
  798.         EXIT LOOP
  799.       CASE ELSE
  800.         IF (ASCII(C$)>31) AND (LEN(Default$)<MaxLength) THEN
  801.           Default$ = Default$ + C$  'Add the new character to the string
  802.           INCR CharCount
  803.         END IF
  804.     END SELECT
  805.   LOOP
  806.  
  807.   LOCATE ,,0   'turn off the cursor
  808.   PRINT        'and move to the next line
  809.  
  810. END SUB
  811.